#include "bondinterestratechart.h"
#include <widgets/chart/basechart_plot.h>
#include <widgets/chart/basechart_graph.h>
#include <core/comdefs.h>
#include <core/time/system_time.h>
#include <core/StyleMgr.h>
#include <uam/ServerTimeMgr.h>
#include <uam/UserAccountManager.h>
#include <bondlib/QBIssuerInfo.h>
#include <widgets/STips.h>

#define CHARTBONDQUOTE_MINSHOW 4.f
#define INTEREST_VERIFY_NUMBER 100000
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#define max(a,b)            (((a) > (b)) ? (a) : (b))

namespace qb
{
	BondInterestRateChart::BondInterestRateChart(QWidget* parent)
		: QWidget(parent)
		, m_nMarketType(0)
		, m_nWndType(wndTp_Null)
		, m_nDataType(data_Null)
		, m_nBtnSelect(0)
		, m_nHotPoint(-1)
		, m_nBegin(0)
		, m_nEnd(0)
		, m_bShowBondRate(false)
		, m_dMinX(0.0)
		, m_dMaxX(0.0)
		, m_dMinY(0.0)
		, m_dMaxY(0.0)
		, m_dOriginMinX(0.0)
		, m_dOriginMaxX(0.0)
		, m_dDragLeft(0.0)
		, m_dDragRight(0.0)
	{
	}

	BondInterestRateChart::~BondInterestRateChart()
	{
	}

	void BondInterestRateChart::setBondInfo(const CBondInfo* bondinfo)
	{
		mBondInfo = (CBondInfo*)bondinfo;
		QB_CHECK_RETURN_VOID1(mBondInfo);

		bool bCurveThis = false, bCurveHis = false, bBondThis = false, bBondHis = false;
		m_nDataType = data_Null;
		m_bShowBondRate = false;
		auto& auth = SSUserAccountManager::instance().GetCDCAutority();
		if (auth.find(7) != auth.end()) m_bShowBondRate = true;//个券隐含评级下调
		if (auth.find(8) != auth.end()) bCurveThis = true; //收益率曲线 - 当年
		if (auth.find(9) != auth.end()) bCurveHis = true;//收益率曲线 - 历史
		if (auth.find(10) != auth.end()) bBondHis = true;//估值数据 - 历史
		if (mBondInfo->IsValidBond() && mBondInfo->IsCDCAuthValid()) bBondThis = true;
		ReloadDataType(bCurveThis, bCurveHis, bBondThis, bBondHis);
	}

	void BondInterestRateChart::loadData(xQBIssuerCreditSpreadAck* pIssuer, xQBBondCreditSpreadAck* pBond)
	{
		inputData(pIssuer, pBond);
		refreshData();
	}

	void BondInterestRateChart::createChart()
	{
		verticalLayout = new QVBoxLayout(this);
		customPlot = new BaseChartCustomPlot(this);
		verticalLayout->addWidget(customPlot);
		this->setLayout(verticalLayout);

		connect(customPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(onMouseMove(QMouseEvent*)));
		connect(customPlot, &BaseChartCustomPlot::mouseDoubleClick, [=]() { emit mouseDoubleClick(this); });
		
		QBrush boxBrush(StyleMgr::instance().color("BasicPlate"));
		customPlot->setBackground(boxBrush);
		customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
		customPlot->xAxis->grid()->setCustomAxisGrid(this);
		customPlot->yAxis->grid()->setCustomAxisGrid(this);
		customPlot->xAxis->setYAxis(customPlot->yAxis);
		customPlot->yAxis->setTickLabelPadding(40);
		customPlot->graph(0)->setPen(QPen(QColor(205, 119, 4)));
		customPlot->graph(0)->setLineStyle(BaseChartGraph::lsLine);
		customPlot->graph(0)->setScatterStyle(BaseChartScatterStyle(BaseChartScatterStyle::ssCircle, 3));
		customPlot->xAxis->setNumberPrecision(4);
		customPlot->xAxis->setCustomGrid();
		customPlot->yAxis->setCustomGrid();
		customPlot->xAxis->setSubTicks(false);
		customPlot->yAxis->setSubTicks(false);
		customPlot->yAxis->ticker()->setTickCount(4);

		QString qText = tr("信用利差(bp)");
		BaseChartTextElement* pte = new BaseChartTextElement(customPlot, qText, QFont("Microsoft YaHei", 9, QFont::Bold));
		pte->setCustomDraw(this);
		pte->setTextFlags(Qt::AlignLeft | Qt::AlignVCenter);
		pte->setTextOffset(18);
		pte->setTextColor(StyleMgr::instance().color("TextNormal"));
		customPlot->plotLayout()->addElement(1, 0, pte);

		bcde = new BaseChartDragBarElement(customPlot);
		customPlot->plotLayout()->addElement(2, 0, bcde);

		refreshData();
	}

	void BondInterestRateChart::setDataType(int type)
	{
		m_nDataType = type;
	}

	void BondInterestRateChart::setWndType(int type)
	{
		m_nWndType = type;
	}

	void BondInterestRateChart::setMarketType(em_BrokerKinds emCurType)
	{
		if (emCurType == em_Exchange)
			m_nMarketType = 2;
		else if (emCurType == em_CFETS)
			m_nMarketType = 1;
		else
			m_nMarketType = 0;
	}

	void BondInterestRateChart::setSelect(int select)
	{
		m_nBtnSelect = select;
	}

	void BondInterestRateChart::setLeftDrag(double ratio)
	{
		QB_CHECK_RETURN_VOID1(customPlot);

		PriceKLineList* pDataKLine = GetPriceKLineList();
		if (!pDataKLine || pDataKLine->m_List.size() <= 0) {
			return;
		}

		double dBegin = ratio * (m_dOriginMaxX - m_dOriginMinX);
		int nBegin = (int)dBegin;
		m_dDragLeft = max(dBegin, m_dOriginMinX + 0.1);
		m_nBegin = max(nBegin, m_dOriginMinX);
	}

	void BondInterestRateChart::setRightDrag(double ratio)
	{
		QB_CHECK_RETURN_VOID1(customPlot);

		PriceKLineList* pDataKLine = GetPriceKLineList();
		if (!pDataKLine || pDataKLine->m_List.size() <= 0) {
			return;
		}

		double dEnd = ratio * (m_dOriginMaxX - m_dOriginMinX);
		int nEnd = (int)dEnd;
		m_dDragRight = min(dEnd, m_dOriginMaxX);
		m_nEnd = min(nEnd + 1, m_dOriginMaxX);
	}

	void BondInterestRateChart::setCentralDrag(double ratio1, double ratio2)
	{
		setLeftDrag(ratio1);
		setRightDrag(ratio2);
	}

	PriceKLineList* BondInterestRateChart::GetPriceKLineList()
	{
		PriceKLineList* pList = &m_DataKLineBroker;
		if (m_nMarketType == 1)pList = &m_DataKLineCFETS;
		else if (m_nMarketType == 2)pList = &m_DataKLineExchange;
		return pList;
	}

	bool BondInterestRateChart::drawGridXLines(BaseChartPainter* painter)
	{
		drawMouseMoveLine(painter);

		PriceKLineList* pDataKLine = GetPriceKLineList();

		int count = 0;
		int firstindex = -1, lastindex = -1;
		for (int i = 0; i <= m_dMaxX; i++) {
			if (i >= m_dMinX && i <= m_dMaxX) {
				if (firstindex < 0)firstindex = i;
				lastindex = i;
				count++;
			}
		}
		if (firstindex < 0 || count <= 0)return true;
		int dx = max(1, (int)(((float)count) / CHARTBONDQUOTE_MINSHOW + 0.4));
		int top = customPlot->yAxis->axisRect()->top();
		int bottom = customPlot->yAxis->axisRect()->bottom();

		std::list<PriceKLine>::iterator it;
		int n = GetKLineIndex(lastindex, it);
		if (n < 0)return true;
		int X, LX;
		QString szText;
		QFont font("Microsoft YaHei");
		font.setPixelSize(12);
		painter->setFont(font);

		if (n == lastindex) 
		{
			szText = GetKLineDateString(it);
			X = customPlot->xAxis->coordToPixel(lastindex);
			painter->drawLine(QLineF(X, bottom, X, top));

			int nFlag = Qt::TextDontClip | Qt::AlignCenter | Qt::AlignVCenter;
			QRectF rect(0, 0, 10000, 10000);
			QRectF measureRect = painter->boundingRect(rect, nFlag, szText);
			QPen oldPen = painter->pen();
			painter->setPen(QColor(128, 128, 128, 255));
			LX = min(customPlot->xAxis->axisRect()->right() - measureRect.width(), X - measureRect.width() / 2);
			painter->drawText(LX, bottom, measureRect.width(), measureRect.height(), nFlag, szText);
			painter->setPen(oldPen);
		}
		else 
		{
			LX = customPlot->xAxis->axisRect()->right();
		}
		int nXEnd = -1;
		int nPreX = customPlot->xAxis->axisRect()->left() + 1;
		int nColLoop = 0;
		int nLastX = -1;
		for (n = firstindex; n < lastindex; n += dx) 
		{
			if (GetKLineIndex(n, it) != n)continue;
			szText = GetKLineDateString(it);
			X = customPlot->xAxis->coordToPixel(n);
			int nFlag = Qt::TextDontClip | Qt::AlignCenter | Qt::AlignVCenter;
			QRectF rect(0, 0, 10000, 10000);
			QRectF measureRect = painter->boundingRect(rect, nFlag, szText);
			if ((X + measureRect.width() / 2) >= LX)continue;
			if (X < nXEnd) continue;
			nXEnd = X + measureRect.width();
			nLastX = nPreX = X;
			painter->drawLine(QLineF(X, bottom, X, top));
			int i = 0;

			QPen oldPen = painter->pen();
			painter->setPen(QColor(128, 128, 128, 255));
			
			for (it = pDataKLine->m_List.begin(); it != pDataKLine->m_List.end(); it++, i++) {
				if (i == n) {
					szText = strInt2DateInTable(it->m_Date);
					QRectF measureRect = painter->boundingRect(rect, nFlag, szText);
					if (n == lastindex)
						if (X + measureRect.width() / 2 > customPlot->xAxis->axisRect()->right())
							painter->drawText(customPlot->xAxis->axisRect()->right() - measureRect.width(), bottom, measureRect.width(), measureRect.height(), nFlag, szText);
						else
							painter->drawText(X - measureRect.width()/2, bottom, measureRect.width(), measureRect.height(), nFlag, szText);
					else
						painter->drawText(X - measureRect.width() / 2, bottom, measureRect.width(), measureRect.height(), nFlag, szText);

					break;
				}
			}

			painter->setPen(oldPen);
		}

		return true;
	}

	bool BondInterestRateChart::drawGridYLines(BaseChartPainter* painter)
	{
		QString szValue;
		QRectF rfText;
		int i = 0;
		int nTextTop = 10000;//纵轴刻度文字
		int top = customPlot->yAxis->axisRect()->top();
		int bottom = customPlot->yAxis->axisRect()->bottom();
		int tickCount = (customPlot->yAxis->ticker()->tickCount() == 0 ? 5 : customPlot->yAxis->ticker()->tickCount());
		double step = (m_dMaxY - m_dMinY) / tickCount;
		QRectF rect(0, 0, 10000, 10000);
		int nFlag = Qt::TextDontClip | Qt::AlignLeft | Qt::AlignVCenter;

		while (1) {
			float price = m_dMinY + step * i;
			int Y = customPlot->yAxis->coordToPixel(price);
			if (Y < top - 1 || Y > bottom) break;
			if (Y <= bottom)
			{
				painter->drawLine(QLineF(customPlot->xAxis->axisRect()->left() - customPlot->yAxis->tickLabelPadding(), Y, customPlot->xAxis->axisRect()->right(), Y));
				szValue = QString("%1").arg((int)(price + 0.5));

				QRectF measureRect = painter->boundingRect(rect, nFlag, szValue);
				if (nTextTop > Y + measureRect.height())
				{
					QPen oldPen = painter->pen();
					painter->setPen(QColor(128, 128, 128, 255));
					painter->drawText(customPlot->xAxis->axisRect()->left() - customPlot->yAxis->tickLabelPadding() + 2, Y - measureRect.height(), measureRect.width(), measureRect.height(), nFlag, szValue);
					painter->setPen(oldPen);
					nTextTop = Y - measureRect.height();
				}
			}
			i++;
			if (i > 100)
				break;
		}

		return true;
	}

	bool BondInterestRateChart::customDraw(BaseChartPainter* painter, const QRect& rect)
	{
		painter->fillRect(rect, QColor(38, 55, 53));
		painter->setPen(QColor(205, 119, 4));
		painter->drawLine(QLineF(rect.left() + 6, rect.top() + rect.height() / 2, rect.left() + 14, rect.top() + rect.height() / 2));
		painter->drawLine(QLineF(rect.left() + 6, rect.top() + rect.height() / 2 + 1, rect.left() + 14, rect.top() + rect.height() / 2 + 1));
		return true;
	}

	void BondInterestRateChart::inputData(xQBIssuerCreditSpreadAck* pIssuer, xQBBondCreditSpreadAck* pBond)
	{
		m_pIssuerData = pIssuer;
		m_pBondData = pBond;

		bool bHaveBond = m_pBondData && m_pBondData->m_list.size() > 0;
		bool bHaveIssuer = m_pIssuerData && m_pIssuerData->m_list.size() > 0;
		if (bHaveBond && bHaveIssuer) m_nWndType = wndTp_Both;
		else if (bHaveBond)m_nWndType = wndTp_Bond;
		else if (bHaveIssuer)m_nWndType = wndTp_Issuer;
		else m_nWndType = wndTp_Null;
	}

	void BondInterestRateChart::refreshData()
	{
		QB_CHECK_RETURN_VOID1(customPlot && customPlot->graph(0));

		transData();

		QVector<double>	vctX, vctY;
		PriceKLineList* pDataKLine = GetPriceKLineList();
		if (pDataKLine->m_List.size() < 6)
		{
			bcde->setEnable(false);
		}
		else
		{
			bcde->setEnable(true);
		}

		m_dOriginMaxX = max(m_dOriginMaxX, pDataKLine->m_List.size() - 1);
		m_dOriginMaxX = min(m_dOriginMaxX, pDataKLine->m_List.size() - 1);

		if (m_nBegin > 0 && m_nBegin < (int)pDataKLine->m_List.size() - 1)
		{
			auto itBegin = pDataKLine->m_List.begin();
			auto itEnd = pDataKLine->m_List.begin();
			std::advance(itEnd, m_nBegin);
			pDataKLine->m_List.erase(itBegin, itEnd);
		}
		if (m_nEnd - m_nBegin > 0 && m_nEnd - m_nBegin < (int)pDataKLine->m_List.size() - 1)
		{
			auto itBegin = pDataKLine->m_List.begin();
			auto itEnd = pDataKLine->m_List.end();
			std::advance(itBegin, m_nEnd - m_nBegin);
			pDataKLine->m_List.erase(itBegin, itEnd);
		}

		auto it = pDataKLine->m_List.begin();
		for (int i = 0; it != pDataKLine->m_List.end(); it++, i++)
		{
			vctX.push_back(i);
			vctY.push_back(it->m_Price1);
		}

		m_dMinX = 0;
		m_dMaxX = CHARTBONDQUOTE_MINSHOW;
		if (pDataKLine->m_List.size() > 0)m_dMaxX = max(m_dMaxX, pDataKLine->m_List.size() - 1);
		
		customPlot->graph(0)->setData(vctX, vctY);
		GetShowLimit(m_dMinX, m_dMaxX, m_dMinY, m_dMaxY);
		double dExt = (m_dMaxX - m_dMinX) / 20;
		customPlot->yAxis->setRange(m_dMinY, m_dMaxY);
		customPlot->xAxis->setRange(m_dMinX, m_dMaxX+ dExt);

		if (pDataKLine->m_List.size() > 0 && m_dDragLeft == 0.0 && m_dDragRight == 0.0)
		{
			int end = m_nEnd;
			if (m_nEnd == 0)
			{
				end = m_dOriginMaxX;
			}

			bcde->setPos(getXPos_Value(m_nBegin), getXPos_Value(end));
		}

		customPlot->replot(BaseChartCustomPlot::rpQueuedReplot);
	}

	void BondInterestRateChart::transData()
	{
		m_mapRating.clear();
		PriceKLineList* pDataKLine = GetPriceKLineList();
		if (!pDataKLine) return;
		pDataKLine->Clear();
		PriceKLine kPrice;
		std::list<xQBBondCreditSpreadAckUnit> ackUnit;
		if (m_nWndType == wndTp_Bond || (m_nWndType == wndTp_Both && m_nBtnSelect == 0)) {
			if (!m_pBondData) return;
			ackUnit = m_pBondData->m_list;
		}
		else if (m_nWndType == wndTp_Issuer || (m_nWndType == wndTp_Both && m_nBtnSelect == 1)) {
			if (!m_pIssuerData) return;
			ackUnit = m_pIssuerData->m_list;
		}
		int nPos = 0;
		qb::base::CTime ct(ServerTimeMgr::instance().serverTime());
		int nThis = ct.GetYear() * 10000 + 101;

		std::list<xQBBondCreditSpreadAckUnit>::const_iterator  itrData = ackUnit.begin();
		for (int i = 0; itrData != ackUnit.end(); itrData++, i++) 
		{
			if (m_nDataType == data_Null 
				|| (m_nDataType == data_CurYear && itrData->m_date < nThis)
				|| (m_nDataType == data_YesYear && itrData->m_date >= nThis))
				continue;

			transData(*itrData, kPrice);
			pDataKLine->Insert(kPrice);
			m_mapRating[nPos++] = *itrData;
		}
	}

	void BondInterestRateChart::transData(const xQBBondCreditSpreadAckUnit& unt, PriceKLine& kData)
	{
		kData.m_Date = unt.m_date;
		kData.m_Price1 = atof(unt.m_spread) * 100;
	}

	void BondInterestRateChart::GetShowLimit(double fMinXShow, double fMaxXShow, double& fMinYShow, double& fMaxYShow) 
	{
		PriceKLineList* pDataKLine = GetPriceKLineList();
		if (pDataKLine->m_List.size() <= 0) {
			m_dMinY = min_show_def;
			m_dMaxY = max_show_def;
			return;
		}

		fMinYShow = INTEREST_VERIFY_NUMBER;
		fMaxYShow = -INTEREST_VERIFY_NUMBER;

		bool bBegin = true;
		std::list<PriceKLine>::iterator it;
		std::list<PriceKLine>::iterator itLast1 = pDataKLine->m_List.end();
		int lastitinwork1 = -1;
		int i = 0;
		bool bEnd1 = false;
		bool bEnd2 = false;
		for (it = pDataKLine->m_List.begin(); it != pDataKLine->m_List.end(); ++it, i++) {
			if (i < fMinXShow) {
				if (it->m_Price1 > 0) {
					itLast1 = it;
					lastitinwork1 = i;
				}
			}
			else {
				if (i <= fMaxXShow) {
					if (it->m_Price1 > 0) {
						if (itLast1 == pDataKLine->m_List.end()) {//first point
							fMinYShow = min(fMinYShow, it->m_Price1);
							fMaxYShow = max(fMaxYShow, it->m_Price1);
						}
						else {
							if (lastitinwork1 < fMinXShow) {
								double fp = (fMinXShow - lastitinwork1) * (it->m_Price1 - itLast1->m_Price1) / (i - lastitinwork1) + itLast1->m_Price1;
								fMinYShow = min(fMinYShow, fp);
								fMaxYShow = max(fMaxYShow, fp);
							}
							fMinYShow = min(fMinYShow, it->m_Price1);
							fMaxYShow = max(fMaxYShow, it->m_Price1);
						}
						itLast1 = it;
						lastitinwork1 = i;
					}
				}
				else {
					if (!bEnd1 && it->m_Price1 > 0) {
						if (itLast1 == pDataKLine->m_List.end()) {
							fMinYShow = min(fMinYShow, it->m_Price1);
							fMaxYShow = max(fMaxYShow, it->m_Price1);
						}
						else {
							if (lastitinwork1 < fMinXShow) {
								double fp = (it->m_Price1 - itLast1->m_Price1) * (fMinXShow - lastitinwork1) / (i - lastitinwork1) + itLast1->m_Price1;
								fMinYShow = min(fMinYShow, fp);
								fMaxYShow = max(fMaxYShow, fp);
							}
							double fp = (it->m_Price1 - itLast1->m_Price1) * (fMaxXShow - lastitinwork1) / (i - lastitinwork1) + itLast1->m_Price1;
							fMinYShow = min(fMinYShow, fp);
							fMaxYShow = max(fMaxYShow, fp);
						}
						bEnd1 = true;
					}
					if (bEnd1)break;
				}
			}
		}

		if (fMinYShow >= INTEREST_VERIFY_NUMBER) { //没有有效数据
			m_dMinY = min_show_def;
			m_dMaxY = max_show_def;
			return;
		}

		fMinYShow = (int)(fMinYShow * 4) / 4.0;
		fMaxYShow = (int)(fMaxYShow * 4) / 4.0;
	}

	int BondInterestRateChart::GetKLineIndex(int nIndex, std::list<PriceKLine>::iterator& it) {
		PriceKLineList* pDataKLine = GetPriceKLineList();
		int i = 0;
		std::list<PriceKLine>::iterator itTemp = pDataKLine->m_List.end();
		for (it = pDataKLine->m_List.begin(); it != pDataKLine->m_List.end(); it++, i++) {
			if (i == nIndex) {
				return i;
			}
			itTemp = it;
		}
		if (it == pDataKLine->m_List.end() && itTemp != pDataKLine->m_List.end()) {
			it = itTemp;
			return pDataKLine->m_List.size() - 1;
		}
		return -1;
	}

	QString	BondInterestRateChart::GetKLineDateString(std::list<PriceKLine>::iterator& it) 
	{
		PriceKLineList* pDataKLine = GetPriceKLineList();
		QString szText;
		if (it != pDataKLine->m_List.end()) {
			szText = strInt2DateInTable(it->m_Date);
		}
		return szText;
	}

	QString	BondInterestRateChart::strInt2DateInTable(UINT nDate) 
	{
		return QString::asprintf("%04d-%02d-%02d", nDate / 10000, (nDate % 10000) / 100, nDate % 100);
	}

	QString BondInterestRateChart::GetPointTips(int pos)
	{
		QString szDate, szDate1;
		int nSz = m_mapRating.size();
		if (pos < 0 || pos >= nSz || m_mapRating.find(pos) == m_mapRating.end()) return "";
		const xQBBondCreditSpreadAckUnit& ackUnt = m_mapRating[pos];

		QString szTip, szRate;
		qb::base::CTime T(ackUnt.m_date / 10000, (ackUnt.m_date % 10000) / 100, ackUnt.m_date % 100, 8, 0, 0);
		int fPrice = int((atof(ackUnt.m_spread) + 0.005) * 100);
		//int fPrice1 = int(atof(ackUnt.m_espread) * 100);
		float yield_avg = atof(ackUnt.m_yield_avg);
		if (yield_avg < 0.0001f && yield_avg > -0.0001f)
		{
			yield_avg = atof(ackUnt.m_Val_Yield);	//无成交，取中债估值
		}

		float gk_Yield = atof(ackUnt.m_gk_Yield);
		float m_zz_Yield = atof(ackUnt.m_zz_Yield);
		if (fPrice > 0.01 /*|| fPrice1 > 0.01*/) {
			if (m_nBtnSelect == 0 && (m_nWndType != wndTp_Issuer)) {//个券
				//信用利差
				szTip = QString("日期 %1-%2-%3").arg(T.GetYear()).arg(T.GetMonth()).arg(T.GetDay());
				szDate = QString("%1 ").arg(fPrice);
				szTip += QString("\n个券信用利差(bp) %1").arg(szDate);

				LoadPointRating(pos, szRate, true);
				if (!szRate.isEmpty()) {
					szTip += ("\n" + szRate);
				}
			}
			else {//主体
				LoadPointRating(pos, szRate, true);
				//信用利差
				szTip = QString("日期 %1-%2-%3").arg(T.GetYear()).arg(T.GetMonth()).arg(T.GetDay());
				szDate = QString("%1 ").arg(fPrice);
				szTip += QString("\n主体信用利差(bp) %1").arg(szDate);

				if (!szRate.isEmpty()) {
					szTip += ("\n" + szRate);
				}
			}
		}

		return szTip;
	}

	void BondInterestRateChart::LoadPointRating(int pos, QString& strRate, bool isTips)
	{
		strRate = "";
		int nSz = m_mapRating.size();
		if (m_nBtnSelect == 0 && !m_bShowBondRate) return;//个券没有权限7不显示隐含评级变动
		if (pos >= nSz || m_mapRating.find(pos) == m_mapRating.end()) return;
		QString strChange, strRatingCur, strRatingFront, strIssure, strPart = "|";
		strChange = QString("%1").arg(m_mapRating[pos].m_rating_change_flag);
		strRatingCur = QString("%1").arg(m_mapRating[pos].m_rating_cur);
		strRatingFront = QString("%1").arg(m_mapRating[pos].m_rating_prev);
		if (m_nBtnSelect == 1 || m_nWndType == wndTp_Issuer) strIssure = QString("%1").arg(m_mapRating[pos].m_issuerCode);
		QStringList arrChange, arrCur, arrFrt, arrIssuer;
		arrChange = strChange.split(strPart);
		arrCur = strRatingCur.split(strPart);
		arrFrt = strRatingFront.split(strPart);
		arrIssuer = strIssure.split(strPart);
		int nLoop = 0, nMax = 9;//最多9个评级
		int nChangeSz = arrChange.size(), nCurSz = arrCur.size(), nFrtSz = arrFrt.size(), nIssuerSz = arrIssuer.size();
		QString strTemp, strChangeComb, strRateComb;
		while (nLoop < nMax) {
			if (nLoop < nChangeSz) {
				if (arrChange[nLoop] != "U" && arrChange[nLoop] != "D") {
					nLoop++;
					continue;
				}
				if (!isTips) {
					if (nLoop < nCurSz && nLoop < nFrtSz) {
						if (!strChangeComb.isEmpty()) strChangeComb += "/";
						if (arrChange[nLoop] == "D") strChangeComb += tr("下调");
						else  strChangeComb += tr("上调");
					}
				}
				else {
					if (nLoop < nCurSz && nLoop < nFrtSz && !arrFrt[nLoop].isEmpty() && !arrCur[nLoop].isEmpty()) {
						if (arrChange[nLoop] == "U") {
							if (m_nBtnSelect == 1 || m_nWndType == wndTp_Issuer) {
								if (!strChangeComb.isEmpty()) strChangeComb += "\n";
								strChangeComb += tr("主体评级上调: ");
							}
							else {
								strChangeComb += tr("隐含评级上调: ");
							}
						}
						else if (arrChange[nLoop] == "D") {
							if (m_nBtnSelect == 1 || m_nWndType == wndTp_Issuer) {
								if (!strChangeComb.isEmpty()) strChangeComb += "\n";
								strChangeComb += tr("主体评级下调: ");
							}
							else {
								strChangeComb += tr("隐含评级下调: ");
							}
						}
						else {
							nLoop++;
							continue;
						}
						strChangeComb += arrFrt[nLoop];
						strChangeComb += "->";
						strChangeComb += arrCur[nLoop];
						if (nLoop < nIssuerSz && !arrIssuer[nLoop].isEmpty()) {
							GetIssuerName(arrIssuer[nLoop], strTemp);
							if (strTemp.isEmpty()) strTemp = "--";
							strChangeComb += ("(" + strTemp + ")");
						}
					}
				}
			}
			nLoop++;
		}
		strRate = strChangeComb;
	}

	void BondInterestRateChart::ReloadDataType(bool curThis, bool curHis, bool bondThis, bool bondHis)
	{
		if (curThis && curHis && bondThis && bondHis) m_nDataType = data_All;
		else if (curThis && bondThis) m_nDataType = data_CurYear;
		else if (curHis & bondHis)m_nDataType = data_YesYear;
	}

	void BondInterestRateChart::GetIssuerName(const QString& issuerCode, QString& issuerName)
	{
		issuerName = "";
		CQBIssuerInfo& IMap = CQBIssuerInfo::instance();
		auto pI = IMap.GetIssuerInfo(issuerCode.toStdString());
		if (pI != NULL) {
			issuerName = QString("%1").arg(pI->field((int)kIssuerInfo::Short_Name_C));
		}
	}

	double BondInterestRateChart::getXPos_Value(double value)
	{
		QB_CHECK_RETURN_VALUE(bcde, 0);

		if (m_dOriginMaxX - m_dOriginMinX == 0) return 0;
		return (value - m_dOriginMinX) / (m_dOriginMaxX - m_dOriginMinX) * bcde->rect().width();
	}

	void BondInterestRateChart::drawMouseMoveLine(BaseChartPainter* painter)
	{
		QB_CHECK_RETURN_VOID1(customPlot);

		int x = mapFromGlobal(QCursor().pos()).x() - 8;
		int y = mapFromGlobal(QCursor().pos()).y() - 8;
		int top = customPlot->yAxis->axisRect()->top();
		int bottom = customPlot->yAxis->axisRect()->bottom();
		int left = customPlot->yAxis->axisRect()->left();
		int right = customPlot->yAxis->axisRect()->right();

		PriceKLineList* pDataKLine = GetPriceKLineList();
		if (pDataKLine && pDataKLine->m_List.size() > 1)
		{
			right = min((int)customPlot->xAxis->coordToPixel(min((int)m_dMaxX, (int)(pDataKLine->m_List.size() - 1))), right);
		}
		else
		{
			right = left;
		}

		if (x < left || x > right || y < top || y > bottom)
		{
			return;
		}

		painter->drawLine(QLineF(x, bottom, x, top));
	}

	void BondInterestRateChart::paintEvent(QPaintEvent* event)
	{
		QStylePainter painter(this);

		painter.fillRect(rect(), StyleMgr::instance().color("BasicPlate"));
	}

	void BondInterestRateChart::leaveEvent(QEvent* event)
	{
		QB_CHECK_RETURN_VOID1(customPlot);

		customPlot->replot();
	}

	void BondInterestRateChart::onMouseMove(QMouseEvent* event)
	{
		QB_CHECK_RETURN_VOID1(customPlot && customPlot->graph(0));

		double dm = customPlot->graph(0)->selectTest(event->pos(), false);
		if (0 < dm && 2 > dm)
		{
			QPen pen(QColor(225, 146, 0));
			pen.setWidth(2);
			customPlot->graph(0)->setPen(pen);
		}
		else
		{
			QPen pen(QColor(205, 119, 4));
			pen.setWidth(1);
			customPlot->graph(0)->setPen(pen);
		}

		customPlot->replot();

		std::list<PriceKLine>::iterator it;
		int i = 0;
		PriceKLineList* pDataKLine = GetPriceKLineList();
		if (!pDataKLine) return;
		for (it = pDataKLine->m_List.begin(); it != pDataKLine->m_List.end(); ++it, i++) {
			int X = customPlot->xAxis->coordToPixel(i);
			if (abs(event->pos().x() - X) < 3) {
				if (m_nHotPoint != i) {
					m_nHotPoint = i;
				}
				QString szTip, szPrice;
				if (it->m_Price1 > 0) {
					szTip = GetPointTips(i);
				}
				if (szTip.length() > 0) {
					std::vector<QBTipCustomItem> vctCustomItem;
					QBTipCustomItem item;
					item.clrNormal = QColor(223, 174, 76, 255);
					item.row = 0;
					item.col = 1;
					vctCustomItem.push_back(item);
					item.row = 1;
					item.col = 2;
					vctCustomItem.push_back(item);
					QBTips::showText(event->screenPos().toPoint(), szTip, this, &vctCustomItem);
				}
				return;
			}
		}
		if (m_nHotPoint >= 0) {
			m_nHotPoint = -1;
			QBTips::hideTip();
		}
	}
}
